home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gchess40.lha / gnuchess4.0p62 / src / search.c < prev    next >
C/C++ Source or Header  |  1993-06-22  |  37KB  |  1,553 lines

  1. /*
  2.  * search.c - C source for GNU CHESS
  3.  *
  4.  * Copyright (c) 1988,1989,1990 John Stanback Copyright (c) 1992 Free Software
  5.  * Foundation
  6.  *
  7.  * This file is part of GNU CHESS.
  8.  *
  9.  * GNU Chess is free software; you can redistribute it and/or modify it under
  10.  * the terms of the GNU General Public License as published by the Free
  11.  * Software Foundation; either version 2, or (at your option) any later
  12.  * version.
  13.  *
  14.  * GNU Chess is distributed in the hope that it will be useful, but WITHOUT ANY
  15.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  16.  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  17.  * details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License along with
  20.  * GNU Chess; see the file COPYING.  If not, write to the Free Software
  21.  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  */
  23. #include "gnuchess.h"
  24. #if !defined OLDTIME && defined HASGETTIMEOFDAY
  25. double pow ();
  26. #endif
  27. short background = 0;
  28. static short int DepthBeyond;
  29. unsigned short int PrVar[MAXDEPTH];
  30. extern char mvstr[4][6];
  31. extern short int recycle, ISZERO;
  32. #ifdef NULLMOVE
  33. short int null;            /* Null-move already made or not */
  34. short int PVari;        /* Is this the PV */
  35. #endif
  36. #ifdef DEBUG40
  37. extern int whichway;
  38. #endif
  39. #ifdef DEBUG
  40.   int xxxtmp;
  41.   int tracetmp;
  42. unsigned short DBLINE[MAXDEPTH];
  43. struct leaf *dbptr;
  44.  
  45. #endif
  46. short int zwndw;
  47. unsigned int TTadd = 1;
  48. short int recycle;
  49.  
  50. #if ttblsz
  51.  
  52. #define CB(i) (unsigned char) ((color[2 * (i)] ? 0x80 : 0)\
  53.            | (board[2 * (i)] << 4)\
  54.            | (color[2 * (i) + 1] ? 0x8 : 0)\
  55.            | (board[2 * (i) + 1]))
  56. inline
  57. int
  58. ProbeTTable (short int side,
  59.          short int depth,
  60.          short int ply,
  61.          short int *alpha,
  62.          short int *beta,
  63.          short int *score)
  64.  
  65. /*
  66.  * Look for the current board position in the transposition table.
  67.  */
  68.  
  69. {
  70.   register struct hashentry *ptbl;
  71.   register /*unsigned*/ short i = 0;    /*to match new type of rehash --tpm*/
  72.  
  73.   ptbl = &ttable[side][hashkey % ttblsize];
  74.   while (true)
  75.     {
  76.       if (ptbl->depth == 0)
  77.     return false;
  78.       if (ptbl->hashbd == hashbd)
  79.     break;
  80.       if (++i > rehash)
  81.     return false;
  82.       ptbl++;
  83.     }
  84.  
  85.   /* rehash max rehash times */
  86.   if ((ptbl->depth >= (short) depth))
  87.     {
  88. #ifdef HASHTEST
  89.       for (i = 0; i < 32; i++)
  90.     {
  91.       if (ptbl->bd[i] != CB (i))
  92.         {
  93. #ifndef BAREBONES
  94.           HashCol++;
  95.           ShowMessage (CP[199]);    /*ttable collision detected*/
  96. #endif
  97.           break;
  98.         }
  99.     }
  100. #endif /* HASHTEST */
  101.  
  102.  
  103.       PV = SwagHt = ptbl->mv;
  104. #ifndef BAREBONES
  105.       HashCnt++;
  106. #endif
  107.       if (ptbl->flags & truescore)
  108.     {
  109.       *score = ptbl->score;
  110.       /* adjust *score so moves to mate is from root */
  111.       if (*score > 9000)
  112.         *score -= ply;
  113.       else if (*score < -9000)
  114.         *score += ply;
  115.       *beta = -20000;
  116.     }
  117.       else if (ptbl->flags & lowerbound)
  118.     {
  119.       if (ptbl->score > *alpha)
  120.         *alpha = ptbl->score - 1;
  121.     }
  122.       return (true);
  123.     }
  124.   return (false);
  125. }
  126.  
  127. inline
  128. int
  129. PutInTTable (short int side,
  130.          short int score,
  131.          short int depth,
  132.          short int ply,
  133.          short int alpha,
  134.          short int beta,
  135.          short unsigned int mv)
  136.  
  137. /*
  138.  * Store the current board position in the transposition table.
  139.  */
  140.  
  141. {
  142.   register struct hashentry *ptbl;
  143.   register /*unsigned*/ short i = 0;    /*to match new type of rehash --tpm*/
  144.  
  145.   ptbl = &ttable[side][hashkey % ttblsize];
  146.   while (true)
  147.     {
  148.       if (ptbl->depth == 0 || ptbl->hashbd == hashbd)
  149.     break;
  150.       if (++i > rehash)
  151.     {
  152. #ifndef BAREBONES
  153.       THashCol++;
  154. #endif
  155.       ptbl += recycle;
  156.       break;
  157.     }
  158.       ptbl++;
  159.     }
  160.  
  161. #ifndef BAREBONES
  162.   TTadd++;
  163.   HashAdd++;
  164. #endif
  165.   /* adjust score so moves to mate is from this ply */
  166.   if (score > 9000)
  167.     score += ply;
  168.   else if (score < -9000)
  169.     score -= ply;
  170.   ptbl->hashbd = hashbd;
  171.   ptbl->depth = (unsigned char) depth;
  172.   ptbl->score = score;
  173.   ptbl->mv = mv;
  174. #ifdef DEBUG4
  175.   if (debuglevel & 32)
  176.     {
  177.       algbr (mv >> 8, mv & 0xff, 0);
  178.       printf ("-add-> h=%lx d=%d s=%d p=%d a=%d b=%d %s\n", hashbd, depth, score, ply, alpha, beta, mvstr);
  179.     }
  180. #endif
  181.   if (score > beta)
  182.     {
  183.       ptbl->flags = lowerbound;
  184.       ptbl->score = beta + 1;
  185.     }
  186.   else
  187.     ptbl->flags = truescore;
  188.  
  189. #ifdef HASHTEST
  190.   for (i = 0; i < 32; i++)
  191.     {
  192.       ptbl->bd[i] = CB (i);
  193.     }
  194. #endif /* HASHTEST */
  195.   return true;
  196. }
  197.  
  198. #endif
  199.  
  200. #include "ataks.h"
  201.  
  202. #include "debug41.h"
  203. /* ............    MOVE GENERATION & SEARCH ROUTINES    .............. */
  204. inline
  205. short int
  206. repetition ()
  207.  
  208. /*  Check for draw by threefold repetition.  */
  209.  
  210. {
  211.   register short i, c, cnt;
  212.   register unsigned short m;
  213.   short b[64];
  214.  
  215.   cnt = c = 0;
  216.   /* try to avoid work */
  217.   if (GameCnt > Game50 + 4)
  218.     {
  219. #if defined(NOMEMSET) || defined(MSDOS)
  220.       for (i = 0; i < 64; b[i++] = 0);
  221. #else
  222.       memset ((char *) b, 0, (unsigned long) sizeof (b));
  223. #endif /* NOMEMSET */
  224.       for (i = GameCnt; i >= Game50; i--)
  225.     {
  226.       m = GameList[i].gmove;
  227.       /* does piece exist on diff board? */
  228.       if (b[m & 0x3f])
  229.         {
  230.           /* does diffs cancel out, piece back? */
  231.           if ((b[m >> 8] += b[m & 0x3f]) == 0)
  232.         --c;
  233.           b[m & 0x3f] = 0;
  234.         }
  235.       else
  236.         {
  237.           /* create diff */
  238.           ++c;
  239.           /* does diff cancel out another diff? */
  240.           if (!(b[m >> 8] -= (b[m & 0x3f] = board[m & 0x3f] +
  241.                   (color[m & 0x3f] << 8))))
  242.         --c;;
  243.         }
  244.       /* if diff count is 0 we have a repetition */
  245.       if (c == 0)
  246.         if ((i ^ GameCnt) & 1)
  247.           cnt++;
  248.     }
  249.     }
  250.   return cnt;
  251. }
  252.  
  253. int plyscore, globalscore;
  254. int
  255. pick (short int p1, short int p2)
  256.  
  257. /*
  258.  * Find the best move in the tree between indexes p1 and p2. Swap the best
  259.  * move into the p1 element.
  260.  *
  261.  */
  262. {
  263.   register struct leaf *p, *q, *r, *k;
  264.   register s0;
  265.   struct leaf temp;
  266.  
  267.   k = p = &Tree[p1];
  268.   q = &Tree[p2];
  269.   s0 = p->score;
  270.   for (r = p + 1; r <= q; r++)
  271.     if ((r->score) > s0)
  272.       {
  273.     s0 = (r->score);
  274.     p = r;
  275.       }
  276.   if (p != k)
  277.     {
  278.       temp = *p;
  279.       *p = *k;
  280.       *k = temp;
  281.       return true;
  282.     }
  283.   return false;
  284. }
  285.  
  286. #ifdef DEBUG
  287. unsigned short trace[MAXDEPTH];
  288. char traceline[256];
  289. unsigned short tracelog[MAXDEPTH];
  290. int tracen = 0;
  291. int traceflag = 0;
  292. int traceply = 0;
  293. #endif
  294. int bookflag = false;
  295. int Jscore = 0;
  296.  
  297. static int TCcount, TCleft;
  298. void
  299. SelectMove (short int side, short int iop)
  300.  
  301.  
  302. /*
  303.  * Select a move by calling function search() at progressively deeper ply
  304.  * until time is up or a mate or draw is reached. An alpha-beta window of
  305.  * -Awindow to +Bwindow points is set around the score returned from the
  306.  * previous iteration. If Sdepth != 0 then the program has correctly
  307.  * predicted the opponents move and the search will start at a depth of
  308.  * Sdepth+1 rather than a depth of 1.
  309.  */
  310.  
  311. {
  312.   static short int i, tempb, tempc, tempsf, tempst, xside, rpt;
  313.   static short int alpha, beta, score;
  314.   static struct GameRec *g;
  315. /*  unsigned long j;*/
  316. #ifdef DEBUG
  317.  
  318.   if (debuglevel & (512 | 1024))
  319.     {
  320.       char b[32];
  321.       short c1, c2, r1, r2;
  322.       tracen = 0;
  323.       traceflag = false;
  324.       traceply = 0;
  325.       tracelog[0] = 0;
  326.       while (true)
  327.     {
  328.       printf ("debug?");
  329.       gets (b);
  330.       if (b[0] == 'p')
  331.         traceply = atoi (&b[1]);
  332.       else if (b[0] == '\0')
  333.         break;
  334.       else
  335.         {
  336.           c1 = b[0] - 'a';
  337.           r1 = b[1] - '1';
  338.           c2 = b[2] - 'a';
  339.           r2 = b[3] - '1';
  340.           trace[++tracen] = (locn (r1, c1) << 8) | locn (r2, c2);
  341.         }
  342.       if (tracen == 0 && traceply > 0)
  343.         traceflag = true;
  344.     }
  345.  
  346.     }
  347. #endif
  348.  
  349.   flag.timeout = false;
  350.   flag.back = false;
  351.   flag.musttimeout = false;
  352.   xside = side ^ 1;
  353.   recycle = (GameCnt % rehash) - rehash;
  354.   /* if background mode set to infinite */
  355.   if (iop == 2)
  356.     {
  357.       ResponseTime = 9999999;
  358.       background = true;
  359.     }
  360.   else
  361.     {
  362.       player = side;
  363.       if (TCflag)
  364.     {
  365.       TCcount = 0;
  366.       background = false;
  367.       if (TimeControl.moves[side] < 1)
  368.         TimeControl.moves[side] = 1;
  369.       /* special case time per move specified */
  370.       if (flag.onemove)
  371.         {
  372.           ResponseTime = TimeControl.clock[side] - 100;
  373.           TCleft = 0;
  374.         }
  375.       else
  376.         {
  377.           /* calculate avg time per move remaining */
  378.           TimeControl.clock[side] += TCadd;
  379.  
  380.           ResponseTime = (TimeControl.clock[side]) / (((TimeControl.moves[side]) * 2) + 1);
  381.           TCleft = (int) ResponseTime / 3;
  382.           ResponseTime += TCadd / 2;
  383.           if (TimeControl.moves[side] < 5)
  384.         TCcount = MAXTCCOUNTX - 10;
  385.         }
  386.       if (ResponseTime < 101)
  387.         {
  388.           ResponseTime = 100;
  389.           TCcount = MAXTCCOUNTX - 10;
  390.         }
  391.       else if (ResponseTime < 200)
  392.         {
  393.           TCcount = MAXTCCOUNTX - 10;
  394.         }
  395.     }
  396.       else
  397.     {
  398.       ResponseTime = MaxResponseTime;
  399.       TCleft = 0;
  400.       ElapsedTime (1);
  401.     }
  402.       if (TCleft)
  403.     {
  404.       TCcount = ((int) ((TimeControl.clock[side] - ResponseTime)) / 2) / TCleft;
  405.       if (TCcount > MAXTCCOUNTX)
  406.         TCcount = 0;
  407.       else
  408.         TCcount = MAXTCCOUNTX - TCcount;
  409.     }
  410.       else
  411.     TCcount = MAXTCCOUNTX;
  412.     }
  413.  
  414.   ExtraTime = 0;
  415.   ExaminePosition ();
  416.   score = ScorePosition (side);
  417. #ifdef QUIETBACKGROUND
  418.   if (!background)
  419. #endif /* QUIETBACKGROUND */
  420.     ShowSidetoMove ();
  421. #ifdef QUIETBACKGROUND
  422.   if (!background)
  423. #endif /* QUIETBACKGROUND */
  424.     SearchStartStuff (side);
  425. #ifdef HISTORY
  426. #if (defined(NOMEMSET) || defined(MSDOS)) && !defined(__GNUC__)
  427.   for (j = 0; j <= 32768; j++)
  428.     history[j] = 0;
  429. #else
  430.   memset ((unsigned char *) history, 0, (unsigned long) sizeof (history));
  431. #endif /* NOMEMSET */
  432. #endif
  433.   FROMsquare = TOsquare = -1;
  434.   PV = 0;
  435.   if (iop == 1)
  436.     hint = 0;
  437.   for (i = 0; i < MAXDEPTH; i++)
  438.     PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  439.   /* set initial window for search */
  440.   alpha = score - ((computer == black) ? BAwindow : WAwindow);
  441.   beta = score + ((computer == black) ? BBwindow : WBwindow);
  442.   rpt = 0;
  443.   TrPnt[1] = 0;
  444.   root = &Tree[0];
  445.   MoveList (side, 1);
  446.   for (i = TrPnt[1]; i < TrPnt[2]; i++)
  447.     if (!pick (i, TrPnt[2] - 1))
  448.       break;
  449.   /* can I get a book move? */
  450.   if (flag.regularstart && Book)
  451.     {
  452.       flag.timeout = bookflag = OpeningBook (&hint, side);
  453.       if (TCflag)
  454.     ResponseTime += ResponseTime;
  455.     }
  456.   /* zero stats for hash table */
  457.   reminus = replus = 0;
  458.   GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
  459.   globalscore = plyscore = score;
  460.   Jscore = 0;
  461.   zwndw = 20;
  462. #include "debug4.h"
  463.   /********************* main loop ********************************/
  464.   Sdepth = (MaxSearchDepth < (MINDEPTH - 1)) ? MaxSearchDepth : (MINDEPTH - 1);
  465.   while (!flag.timeout)
  466.     {
  467.       /* go down a level at a time */
  468.       Sdepth++;
  469. #ifdef NULLMOVE
  470.       null = 0;
  471.       PVari = 1;
  472. #endif
  473.       DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
  474.  
  475. #ifndef BAREBONES
  476. #ifdef QUIETBACKGROUND
  477.       if (!background)
  478. #endif /* QUIETBACKGROUND */
  479.     ShowDepth (' ');
  480. #endif
  481.       /* search at this level returns score of PV */
  482.       score = search (side, 1, Sdepth, alpha, beta, PrVar, &rpt);
  483.       /* save PV as killer */
  484.       for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
  485.  
  486.       /* low search failure re-search with (-inf,score) limits  */
  487.       if (score < alpha)
  488.     {
  489. #ifndef BAREBONES
  490.       reminus++;
  491. #ifdef QUIETBACKGROUND
  492.       if (!background)
  493. #endif /* QUIETBACKGROUND */
  494.         ShowDepth ('-');
  495. #endif
  496.       if (TCflag && TCcount < MAXTCCOUNTR)
  497.         {
  498.           TCcount = MAXTCCOUNTR - 1;
  499.           ExtraTime += (8 * TCleft);
  500.         }
  501.  
  502.       score = search (side, 1, Sdepth, -9999, 9999, PrVar, &rpt);
  503.     }
  504.       /* high search failure re-search with (score, +inf) limits */
  505.       else if (score > beta && !(root->flags & exact))
  506.     {
  507. #ifndef BAREBONES
  508.       replus++;
  509. #ifdef QUIETBACKGROUND
  510.       if (!background)
  511. #endif /* QUIETBACKGROUND */
  512.         ShowDepth ('+');
  513. #endif
  514.       score = search (side, 1, Sdepth, -9999, 9999, PrVar, &rpt);
  515.     }
  516.       /**************** out of search ********************************************/
  517.       if (flag.musttimeout || Sdepth >= MaxSearchDepth)
  518.     flag.timeout = true;
  519.  
  520.       else if (TCflag && (Sdepth > (MINDEPTH - 1)) && (TCcount < MAXTCCOUNTR))
  521.     {
  522.       if (killr0[1] != PrVar[1] /* || Killr0[2] != PrVar[2] */ )
  523.         {
  524.           TCcount++;
  525.           ExtraTime += TCleft;
  526.         }
  527.       if ((abs (score - globalscore) / Sdepth) > ZDELTA)
  528.         {
  529.           TCcount++;
  530.           ExtraTime += TCleft;
  531.         }
  532.     }
  533.       if (score > (Jscore - zwndw) && score > (Tree[1].score + 250))
  534.     ExtraTime = 0;
  535.       ElapsedTime (2);
  536.       if (root->flags & exact)
  537.     flag.timeout = true;
  538.       /*else if (Tree[1].score < -9000) flag.timeout = true;*/
  539. #if defined OLDTIME || !defined HASGETTIMEOFDAY
  540.       else if (!(Sdepth < MINDEPTH) && TCflag && ((4 * et) > (2 * ResponseTime + ExtraTime)))
  541.     flag.timeout = true;
  542. #else
  543.       else if (!(Sdepth < MINDEPTH) && TCflag &&
  544.            ((int) (1.93913099l * (pow ((double) et, 1.12446928l))) > (ResponseTime + ExtraTime)))
  545.     flag.timeout = true;
  546. #endif
  547.       /************************ time control ***********************************/
  548.  
  549.       /* save PV as killer */
  550.       for (i = 1; i <= Sdepth + 1; i++)
  551.     killr0[i] = PrVar[i];
  552.       if (!flag.timeout)
  553.     Tscore[0] = score;
  554.       /* if (!flag.timeout) */
  555. /*
  556.       for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
  557.     if (!pick (i, TrPnt[2] - 1))
  558.       break;
  559. /*
  560.       /* if done or nothing good to look at quit */
  561.       if ((root->flags & exact) || (score < -9000))
  562.     flag.timeout = true;
  563.       /* find the next best move put below root */
  564. #include "debug13.h"
  565.       if (!flag.timeout)
  566.     {
  567.       /* */
  568. #if !defined NODYNALPHA
  569.       Jscore = (plyscore + score) >> 1;
  570. #endif
  571.       zwndw = 20 + abs (Jscore / 12);
  572.       plyscore = score;
  573.       /* recompute search window */
  574.       beta = score + ((computer == black) ? BBwindow : WBwindow);
  575. #if !defined NODYNALPHA
  576.       alpha = ((Jscore < score) ? Jscore : score) - ((computer == black) ? BAwindow : WAwindow) - zwndw;
  577. #else
  578.       alpha = score - ((computer == black) ? BAwindow : WAwindow);
  579. #endif
  580.     }
  581. #ifndef BAREBONES
  582. #ifdef QUIETBACKGROUND
  583.       if (!background)
  584. #endif /* QUIETBACKGROUND */
  585.     ShowResults (score, PrVar, '.');
  586. #ifdef DEBUG41
  587.       debug41 (score, PrVar, '.');
  588. #endif
  589. #endif
  590. #include "debug16.h"
  591.     }
  592.   /******************************* end of main loop ***********************************/
  593.   /* background mode */
  594.   if (iop == 2)
  595.     return;
  596. #include "debug4.h"
  597.   if (rpt >= 2)
  598.     {
  599.       root->flags |= draw;
  600.       DRAW = CP[101];        /* Repetition */
  601.     }
  602.   else
  603.     /* if no moves and not in check then draw */
  604.   if ((score == -9999) && !(SqAtakd (PieceList[side][0], xside)))
  605.     {
  606.       root->flags |= draw;
  607.       DRAW = CP[87];        /* No moves */
  608.     }
  609.   else if (GameCnt == MAXMOVES)
  610.     {
  611.       root->flags |= draw;
  612.       DRAW = CP[80];        /* Max Moves */
  613.     }
  614.   /* not in book so set hint to guessed move for other side */
  615.   if (!bookflag)
  616.     hint = ((PrVar[1]) ? PrVar[2] : 0);
  617.  
  618.   /* if not mate or draw make move and output it */
  619.   if (((score > -9999) && (rpt <= 2)) || (root->flags & draw))
  620.     {
  621.       MakeMove (side, &Tree[0], &tempb, &tempc, &tempsf, &tempst, &INCscore);
  622. #if !defined NOMATERIAL
  623.       if (flag.material && !pmtl[black] && !pmtl[white] && (mtl[white] < (valueR + valueK)) && (mtl[black] < (valueR + valueK)))
  624.     {
  625.       root->flags |= draw;
  626.       DRAW = CP[224];    /* No pieces */
  627.     }
  628.       else
  629. #endif
  630.       if (!PieceCnt[black] && !PieceCnt[white])
  631.     {
  632.       root->flags |= draw;
  633.       DRAW = CP[88];    /* No pieces */
  634.     }
  635.       algbr (root->f, root->t, (short) root->flags);
  636.     }
  637.   else
  638.     {
  639.       algbr (0, 0, 0);        /* Zero move string when mate. */
  640.       root->score = score;    /* When mate, ignore distinctions!
  641.                  * --SMC */
  642.     }
  643.   g = &GameList[GameCnt];
  644.   if (g->flags & capture && g->piece == king)
  645.     {
  646.       flag.mate = flag.illegal = true;
  647.     }
  648.   /* If Time Control get the elapsed time */
  649.   if (TCflag)
  650.     ElapsedTime (1);
  651. #ifdef XBOARD
  652.   OutputMove (score, PrVar);
  653. #else
  654.   OutputMove ();
  655. #endif
  656.   /* if mate set flag */
  657.   if ((score == -9999 || score == 9998))
  658.     flag.mate = true;
  659.   /* if mate clear hint */
  660.   if (flag.mate)
  661.     hint = 0;
  662.   /* if pawn move or capture or castle or promote zero repitition array */
  663.   if ((board[root->t] == pawn) || (root->flags & (capture | cstlmask | promote)))
  664.     {
  665.       Game50 = GameCnt;
  666.       ZeroRPT ();
  667.     }
  668.   /* add move to game list */
  669.   g->score = score;
  670.   g->nodes = NodeCnt;
  671.   g->time = (et + 50) / 100;
  672. /*
  673.   g->time = TCcount;
  674. */
  675.   g->depth = Sdepth;
  676. #include "debug40.h"
  677.   /* update time comtrol info */
  678.   if (TCflag)
  679.     {
  680. #if defined CHESSTOOL || defined XBOARD
  681.       TimeControl.clock[side] -= (et + OperatorTime + 45);
  682.       timecomp[compptr] = (et + OperatorTime + 45);
  683. #else
  684.       TimeControl.clock[side] -= (et + OperatorTime);
  685.       timecomp[compptr] = (et + OperatorTime);
  686. #endif
  687.       /* finished our required moves - setup the next set */
  688.       --TimeControl.moves[side];
  689.     }
  690.   /* check for end conditions */
  691.   if ((root->flags & draw) /* && flag.bothsides */ )
  692. #if !defined CLIENT
  693.     flag.mate = true;
  694. #else
  695.     ;
  696. #endif
  697.   else if (GameCnt == MAXMOVES)
  698.     {
  699.       flag.mate = true;
  700.     }
  701.   /* out of move store, you loose */
  702.   else
  703.     /* switch to other side */
  704.     player = xside;
  705.   Sdepth = 0;
  706. }
  707.  
  708.  
  709. int
  710. search (short int side,
  711.     register short int ply,
  712.     register short int depth,
  713.     short int alpha,
  714.     short int beta,
  715.     short unsigned int *bstline,
  716.     short int *rpt)
  717.  
  718. /*
  719.  * Perform an alpha-beta search to determine the score for the current board
  720.  * position. If depth <= 0 only capturing moves, pawn promotions and
  721.  * responses to check are generated and searched, otherwise all moves are
  722.  * processed. The search depth is modified for check evasions, certain
  723.  * re-captures and threats. Extensions may continue for up to 11 ply beyond
  724.  * the nominal search depth.
  725.  */
  726.  
  727.  
  728. {
  729.   register short j, pnt;
  730.   short tempb, tempc, tempsf, tempst;
  731.   short xside, pbst, score, rcnt, slk, InChk;
  732.   unsigned short mv, nxtline[MAXDEPTH];
  733.   struct leaf *node, tmp;
  734.   short best = -12000;
  735.   short bestwidth = 0;
  736. #ifdef NULLMOVE
  737.   short int PVsave;
  738.   short int PVarisave;
  739. #endif
  740.   NodeCnt++;
  741.   /* look every ZNODE nodes for a timeout */
  742. #ifdef NULLMOVE
  743.   if (!null)
  744.     {
  745. #endif
  746.       if (NodeCnt > ETnodes)
  747.     {
  748.       ElapsedTime (2);
  749.       if (flag.back)
  750.         {
  751.           flag.back = false;
  752.           flag.timeout = true;
  753.           flag.musttimeout = false;
  754.         }
  755.       else if (TCflag || MaxResponseTime)
  756.         {
  757.           if ((et >= (ResponseTime + ExtraTime)) && Sdepth > MINDEPTH )
  758.         {        /* try to extend to finish ply */
  759.           if (flag.back || (TCflag && TCcount < MAXTCCOUNTX))
  760.             {
  761.               flag.back = false;
  762.               flag.musttimeout = true;
  763.               TCcount += 1;
  764.               ExtraTime += TCleft;
  765.             }
  766.           else
  767.             {
  768.               flag.back = false;
  769.               flag.timeout = true;
  770.               flag.musttimeout = false;
  771.             }
  772.         }
  773.         }
  774.       else if (flag.back)
  775.         {
  776.           flag.back = false;
  777.           flag.timeout = true;
  778.           flag.musttimeout = false;
  779.         }
  780.  
  781.     }
  782.       else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
  783.     {
  784.       flag.timeout = true;
  785.       flag.musttimeout = false;
  786.     }
  787. #ifdef NULLMOVE
  788.     }
  789. #endif
  790.   xside = side ^ 1;
  791.   /* slk is lone king indicator for either side */
  792.   score = evaluate (side, ply, alpha, beta, INCscore, &InChk);
  793.  
  794.   /*
  795.    * check for possible repitition if so call repitition - rpt is
  796.    * repeat count
  797.    */
  798.   if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
  799.     {
  800.       *rpt = repetition ();
  801.  
  802.       /*
  803.        * repeat position >2 don't need to return score it's taken
  804.        * care of above
  805.        */
  806.       if (*rpt == 1)
  807.     score /= 2;
  808.     }
  809.   else
  810.     *rpt = 0;
  811.  
  812.   /* score > 9000 its a draw or mate */
  813.   if (score > 9000)
  814.     {
  815.       bstline[ply] = 0;
  816.       return (score);
  817.     }
  818.   /* Do we need to add depth because of special conditions */
  819.   /* if in check or pawn threat or in capture sequence search deeper */
  820.   /*************************************** depth extensions ***********************************/
  821.   if (depth > 0)
  822.     {
  823.       /* Allow opponent a chance to check again */
  824.       if (InChk)
  825.     depth = (depth < 2) ? 2 : depth;
  826.       else if (PawnThreat[ply - 1] ||
  827.            (flag.rcptr && (score > alpha) &&
  828.       (score < beta) && (ply > 2) && CptrFlag[ply - 1] && CptrFlag[ply - 2]))
  829.     ++depth;
  830.     }
  831.   else
  832.     {
  833.       if (score >= alpha &&
  834.       (InChk || PawnThreat[ply - 1] || (hung[side] > 1 && ply == Sdepth + 1)))
  835.     depth = 1;
  836.       else if (score <= beta &&
  837.            ((ply < Sdepth + 4) && (ply > 4) &&
  838.         ChkFlag[ply - 2] && ChkFlag[ply - 4] &&
  839.         ChkFlag[ply - 2] != ChkFlag[ply - 4]))
  840.     depth = 1;
  841.     }
  842.   /*******************************************************************************************/
  843.   /* try the local transition table if it's there */
  844. #if ttblsz
  845.   if ( /*depth > 0 &&*/ flag.hash && ply > 1)
  846.     {
  847.       if (ProbeTTable (side, depth, ply, &alpha, &beta, &score) == true)
  848.     {
  849.       bstline[ply] = PV;
  850.       bstline[ply + 1] = 0;
  851. #include "debug64.h"
  852.       if (beta == -20000)
  853.         return (score);
  854.       if (alpha > beta)
  855.         return (alpha);
  856.     }
  857. #ifdef HASHFILE
  858.       /* ok try the transition file if its there */
  859.       else if (hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit)
  860.      && (ProbeFTable (side, depth, ply, &alpha, &beta, &score) == true))
  861.     {
  862.           PutInTTable (side, score, depth, ply, alpha, beta, PV);
  863.           bstline[ply] = PV;
  864.           bstline[ply + 1] = 0;
  865.           if (beta == -20000)
  866.         return (score);
  867.           if (alpha > beta)
  868.         return (alpha);
  869. #include "debug10.h"
  870.     }
  871. #endif /* HASHFILE */
  872.     }
  873. #endif /* ttblsz */
  874.  
  875.   /*
  876.    * if more then DepthBeyond ply past goal depth or at goal depth and
  877.    * score > beta quit - means we are out of the window
  878.    */
  879.   if (ply > DepthBeyond || (depth < 1 && score > beta))
  880.     {
  881.       return (score);
  882.     }
  883.  
  884.   /*
  885.    * if below first ply and not at goal depth generate all moves else
  886.    * only capture moves
  887.    */
  888.   if (ply > 1)
  889.     if (depth > 0 || ply < (SDEPTHLIM) ||
  890.     (background && ply < Sdepth + 2))
  891.       {
  892.     MoveList (side, ply);
  893.       }
  894.     else
  895.       {
  896.     CaptureList (side, ply);
  897.       }
  898.  
  899.   /* no moves return what we have */
  900.  
  901.   /*
  902.    * normally a search will continue til past goal and no more capture
  903.    * moves exist
  904.    */
  905.   /* unless it hits DepthBeyond */
  906.   if (TrPnt[ply] == TrPnt[ply + 1])
  907.     {
  908.       return (score);
  909.     }
  910.  
  911.  
  912.  
  913.   /* if not at goal set best = -inf else current score */
  914.   best = (depth > 0) ? -12000 : score;
  915. #ifdef NULLMOVE
  916.  
  917.   PVarisave = PVari;
  918.   if (!null &&            /* no previous null-move */
  919.       !PVari &&            /* no null-move during the PV */
  920.       (ply > 2) &&        /* not at ply 1 */
  921.       (ply <= Sdepth) &&
  922.       (depth > 3) &&
  923.       !InChk &&            /* no check */
  924.       ((mtl[side] + mtl[xside]) > NULLMOVELIM))
  925.     /* enough material such that zugzwang is unlike but who knows which value
  926.        is suitable? */
  927.     {
  928.  
  929.       /* ok, we make a null move, i.e.  this means we have nothing to do
  930.       but we have to keep the some arrays up to date otherwise gnuchess
  931.       gets confused.  Maybe somebody knows exactly which informations are
  932.      important and which not.
  933.  
  934.      Another idea is that we try the null-move first and generate the
  935.      moves later.  This may save time but we have to take care that
  936.      PV and other variables contain the right value so that the move
  937.      ordering works right.
  938.      */
  939.       register struct GameRec *g;
  940.  
  941.       nxtline[ply + 1] = 0;
  942.       CptrFlag[ply] = 0;
  943.       PawnThreat[ply] = 0;
  944.       Tscore[ply] = score;
  945.       PVsave = PV;
  946.       PV = 0;
  947.       null = 1;
  948.       g = &GameList[++GameCnt];
  949.       g->hashkey = hashkey;
  950.       g->hashbd = hashbd;
  951.       epsquare = -1;
  952.       TOsquare = -1;
  953.       g->Game50 = Game50;
  954.       g->gmove = -1;
  955.       g->flags = 0;
  956.       g->piece = 0;
  957.       g->color = neutral;
  958.  
  959.       best = -search (xside, ply + 1, depth - 2, -beta - 1, -beta, nxtline, &rcnt);
  960.       null = 0;
  961.       PV = PVsave;
  962.       GameCnt--;
  963.     if (best < alpha) best = -12000;
  964.       else if (best > beta) return (best);
  965.       else best = -12000;
  966.     }
  967. #endif
  968.   /* if best so far is better than alpha set alpha to best */
  969.   if (best > alpha)
  970.     alpha = best;
  971.   /********************** main loop ************************************************************************/
  972.   /* look at each move until no more or beta cutoff */
  973.   for (pnt = pbst = TrPnt[ply]; pnt < TrPnt[ply + 1] && best <= beta; pnt++)
  974.     {
  975.       /* find the most interesting looking of the remaining moves */
  976.       if (ply > 1)
  977.     pick (pnt, TrPnt[ply + 1] - 1);
  978. #ifdef NULLMOVE
  979.       PVari = PVarisave && (pnt == TrPnt[ply]);    /* Is this the PV? */
  980. #endif
  981.  
  982.       node = &Tree[pnt];
  983.       /* is this a forbidden move */
  984.       if (ply == 1 && node->score == -32768) continue;
  985. #ifdef DEBUG
  986.       if (debuglevel & (512 | 1024))
  987.     {
  988.       if (!tracen)
  989.         traceflag = ((ply > traceply) ? false : true);
  990.       else if (ply <= tracen && (ply == 1 || traceflag))
  991.         {
  992.           if (trace[ply] == (Tree[pnt].t | (Tree[pnt].f << 8)))
  993.         traceflag = true;
  994.           else
  995.         traceflag = false;
  996.         }
  997.       tracelog[ply] = (Tree[pnt].t | (Tree[pnt].f << 8));
  998.       tracelog[ply + 1] = 0;
  999.     }
  1000. #endif
  1001.       nxtline[ply + 1] = 0;
  1002.  
  1003. #ifndef BAREBONES
  1004.       /* if at top level */
  1005.       if (ply == 1)
  1006.     {            /* at the top update search status */
  1007.       if (flag.post)
  1008. #ifdef QUIETBACKGROUND
  1009.         if (!background)
  1010. #endif /* QUIETBACKGROUND */
  1011.           ShowCurrentMove (pnt, node->f, node->t);
  1012.     }
  1013. #endif
  1014.       if (!(node->flags & exact))
  1015.     {
  1016.       /* make the move and go deeper */
  1017.       MakeMove (side, node, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  1018.       CptrFlag[ply] = (node->flags & capture);
  1019.       PawnThreat[ply] = (node->flags & pwnthrt);
  1020.       Tscore[ply] = node->score;
  1021.       PV = node->reply;
  1022. #ifdef DEBUG
  1023.       xxxtmp = node->score;
  1024.       tracetmp = traceflag;
  1025. #endif
  1026.       node->score = -search (xside, ply + 1,
  1027.                  (depth > 0) ? depth - 1 : 0,
  1028.                  -beta, -alpha,
  1029.                  nxtline, &rcnt);
  1030. /*
  1031.           if(!flag.timeout)node->score = score;
  1032. */
  1033.       node->width = (ply % 2 == 1) ? (TrPnt[ply + 2] - TrPnt[ply + 1]) : 0;
  1034.       if (abs (node->score) > 9000)
  1035.         node->flags |= exact;
  1036.       else if (rcnt == 1)
  1037.         node->score /= 2;
  1038. #include "debug256.h"
  1039.       if ((rcnt >= 2 || GameCnt - Game50 > 99 || (node->score == 9999 - ply && !ChkFlag[ply])))
  1040.         {
  1041.           node->flags |= (draw | exact);
  1042.           DRAW = CP[58];    /* Draw */
  1043.           node->score = ((side == computer) ? contempt : -contempt);
  1044.         }
  1045.       node->reply = nxtline[ply + 1];
  1046.       /* reset to try next move */
  1047.       UnmakeMove (side, node, &tempb, &tempc, &tempsf, &tempst);
  1048.     }
  1049.       /* if best move so far */
  1050.       if (!flag.timeout && ((node->score > best) || ((node->score == best) && (node->width > bestwidth))))
  1051.     {
  1052.       /*
  1053.        * all things being equal pick the denser part of the
  1054.        * tree
  1055.        */
  1056.       bestwidth = node->width;
  1057.  
  1058.       /*
  1059.        * if not at goal depth and better than alpha and not
  1060.        * an exact score increment by depth
  1061.        */
  1062.       if (depth > 0 && node->score > alpha && !(node->flags & exact))
  1063.         node->score += depth;
  1064.       best = node->score;
  1065.       pbst = pnt;
  1066.       if (best > alpha)
  1067.         {
  1068.           alpha = best;
  1069.         }
  1070.       /* update best line */
  1071.       for (j = ply + 1; nxtline[j] > 0; j++)
  1072.         bstline[j] = nxtline[j];
  1073.       bstline[j] = 0;
  1074.       bstline[ply] = (node->f << 8) | node->t;
  1075.       /* if at the top */
  1076.       if (ply == 1)
  1077.         {
  1078.           /*
  1079.            * if its better than the root score make it
  1080.            * the root
  1081.            */
  1082.           if ((best > root->score) || ((best == root->score) && (bestwidth > root->width)))
  1083.         {
  1084.           tmp = Tree[pnt];
  1085.           for (j = pnt - 1; j >= 0; j--)
  1086.             Tree[j + 1] = Tree[j];
  1087.           Tree[0] = tmp;
  1088.           pbst = 0;
  1089.         }
  1090. #ifndef BAREBONES
  1091. #ifdef QUIETBACKGROUND
  1092.           if (!background)
  1093. #endif /* QUIETBACKGROUND */
  1094.         if (Sdepth > 2)
  1095.           if (best > beta)
  1096.             {
  1097.               ShowResults (best, bstline, '+');
  1098. #ifdef DEBUG41
  1099.               debug41 (best, bstline, '+');
  1100. #endif
  1101.             }
  1102.           else if (best < alpha)
  1103.             {
  1104.               ShowResults (best, bstline, '-');
  1105. #ifdef DEBUG41
  1106.               debug41 (best, bstline, '-');
  1107. #endif
  1108.             }
  1109.           else
  1110.             ShowResults (best, bstline, '&');
  1111. #ifdef DEBUG41
  1112.           debug41 (best, bstline, '&');
  1113. #endif
  1114. #endif
  1115.           if (!background && Sdepth > 2){
  1116.              if( best < alpha ) { TCcount = 0;ExtraTime += 9*TCleft;}
  1117.                  }
  1118.         }
  1119.     }
  1120.       if (flag.timeout)
  1121.     {
  1122.       return (Tscore[ply - 1]);
  1123.     }
  1124.     }
  1125.  
  1126.   /******************************************************************************************/
  1127.   node = &Tree[pbst];
  1128.   mv = (node->f << 8) | node->t;
  1129. #ifdef NULLMOVE
  1130.   PVari = PVarisave;
  1131. #endif
  1132. #ifdef DEBUG
  1133. #include "debug512.h"
  1134. #endif
  1135.  
  1136.   /*
  1137.    * we have a move so put it in local table - if it's already there
  1138.    * done else if not there or needs to be updated also put it in
  1139.    * hashfile
  1140.    */
  1141. #if ttblsz
  1142.   if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
  1143.     {
  1144.       if (PutInTTable (side, best, depth, ply, alpha, beta, mv)
  1145. #ifdef HASHFILE
  1146.       && hashfile && (depth > HashDepth) && (GameCnt < HashMoveLimit))
  1147.     {
  1148.       PutInFTable (side, best, depth, ply, alpha, beta, node->f, node->t);
  1149.     }
  1150. #else
  1151.     );
  1152. #endif /* HASHFILE */
  1153.     }
  1154. #endif /* ttblsz */
  1155.   if (depth > 0)
  1156.     {
  1157. #ifdef HISTORY
  1158.       j = (node->f << 6) | node->t;
  1159.       if (side == black)
  1160.     j |= 0x4000;
  1161.       if (history[j] < HISTORYLIM)
  1162.     history[j] += (unsigned short) 1 << depth;
  1163. #endif
  1164.       if (node->t != (short) (GameList[GameCnt].gmove & 0xFF))
  1165.     if (best <= beta)
  1166.       killr3[ply] = mv;
  1167.     else if (mv != killr1[ply])
  1168.       {
  1169.         killr2[ply] = killr1[ply];
  1170.         killr1[ply] = mv;
  1171.       }
  1172.       killr0[ply] = ((best > 9000) ? mv : 0);
  1173.     }
  1174.   return (best);
  1175. }
  1176.  
  1177.  
  1178.  
  1179.  
  1180. int
  1181. castle (short int side, short int kf, short int kt, short int iop)
  1182.  
  1183. /* Make or Unmake a castling move. */
  1184.  
  1185. {
  1186.   register short rf, rt, t0, xside;
  1187.  
  1188.   xside = side ^ 1;
  1189.   if (kt > kf)
  1190.     {
  1191.       rf = kf + 3;
  1192.       rt = kt - 1;
  1193.     }
  1194.   else
  1195.     {
  1196.       rf = kf - 4;
  1197.       rt = kt + 1;
  1198.     }
  1199.   if (iop == 0)
  1200.     {
  1201.       if (kf != kingP[side] ||
  1202.       board[kf] != king ||
  1203.       board[rf] != rook ||
  1204.       color[kf] != side ||
  1205.       color[rf] != side ||
  1206.       Mvboard[kf] != 0 ||
  1207.       Mvboard[rf] != 0 ||
  1208.       color[kt] != neutral ||
  1209.       color[rt] != neutral ||
  1210.       color[kt - 1] != neutral ||
  1211.       SqAtakd (kf, xside) ||
  1212.       SqAtakd (kt, xside) ||
  1213.       SqAtakd (rt, xside))
  1214.     return (false);
  1215.     }
  1216.   else
  1217.     {
  1218.       if (iop == 1)
  1219.     {
  1220.       castld[side] = true;
  1221.       Mvboard[kf]++;
  1222.       Mvboard[rf]++;
  1223.     }
  1224.       else
  1225.     {
  1226.       castld[side] = false;
  1227.       Mvboard[kf]--;
  1228.       Mvboard[rf]--;
  1229.       t0 = kt;
  1230.       kt = kf;
  1231.       kf = t0;
  1232.       t0 = rt;
  1233.       rt = rf;
  1234.       rf = t0;
  1235.     }
  1236.       board[kt] = king;
  1237.       color[rt] = color[kt] = side;
  1238.       Pindex[kt] = 0;
  1239.       board[kf] = no_piece;
  1240.       color[rf] = color[kf] = neutral;
  1241.       board[rt] = rook;
  1242.       Pindex[rt] = Pindex[rf];
  1243.       board[rf] = no_piece;
  1244.       PieceList[side][Pindex[kt]] = kt;
  1245.       PieceList[side][Pindex[rt]] = rt;
  1246.       UpdateHashbd (side, king, kf, kt);
  1247.       UpdateHashbd (side, rook, rf, rt);
  1248.     }
  1249.   return (true);
  1250. }
  1251.  
  1252.  
  1253. void
  1254. EnPassant (short int xside, short int f, short int t, short int iop)
  1255.  
  1256. /*
  1257.  * Make or unmake an en passant move.
  1258.  */
  1259.  
  1260. {
  1261.   register short l;
  1262.  
  1263.   l = t + ((t > f) ? -8 : 8);
  1264.   if (iop == 1)
  1265.     {
  1266.       board[l] = no_piece;
  1267.       color[l] = neutral;
  1268.     }
  1269.   else
  1270.     {
  1271.       board[l] = pawn;
  1272.       color[l] = xside;
  1273.     }
  1274.   InitializeStats ();
  1275. }
  1276.  
  1277.  
  1278. void
  1279. UpdatePieceList (short int side, short int sq, short int iop)
  1280.  
  1281. /*
  1282.  * Update the PieceList and Pindex arrays when a piece is captured or when a
  1283.  * capture is unmade.
  1284.  */
  1285.  
  1286. {
  1287.   register short i;
  1288.  
  1289.   if (iop == 1)
  1290.     {
  1291.       PieceCnt[side]--;
  1292.       for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
  1293.     {
  1294.       PieceList[side][i] = PieceList[side][i + 1];
  1295.       Pindex[PieceList[side][i]] = i;
  1296.     }
  1297.     }
  1298.   else
  1299.     {
  1300.       PieceCnt[side]++;
  1301.       PieceList[side][PieceCnt[side]] = sq;
  1302.       Pindex[sq] = PieceCnt[side];
  1303.     }
  1304. }
  1305.  
  1306. void
  1307. MakeMove (short int side,
  1308.       struct leaf *node,
  1309.       short int *tempb,    /* color of to square */
  1310.       short int *tempc,    /* piece at to square */
  1311.       short int *tempsf,    /* static value of piece on from */
  1312.       short int *tempst,    /* static value of piece on to */
  1313.       short int *INCscore)    /* score increment for pawn structure change */
  1314.  
  1315. /*
  1316.  * Update Arrays board[], color[], and Pindex[] to reflect the new board
  1317.  * position obtained after making the move pointed to by node. Also update
  1318.  * miscellaneous stuff that changes when a move is made.
  1319.  */
  1320.  
  1321. {
  1322.   register short f, t, xside, ct, cf;
  1323.   register struct GameRec *g;
  1324.  
  1325.   xside = side ^ 1;
  1326.   g = &GameList[++GameCnt];
  1327.   g->hashkey = hashkey;
  1328.   g->hashbd = hashbd;
  1329.   g->epssq = epsquare;
  1330.   f = node->f;
  1331.   t = node->t;
  1332.   epsquare = -1;
  1333.   /* FROMsquare = f;*/
  1334.   TOsquare = t;
  1335.   *INCscore = 0;
  1336.   g->Game50 = Game50;
  1337.   g->gmove = (f << 8) | t;
  1338.   g->flags = node->flags;
  1339.   if (node->flags & cstlmask)
  1340.     {
  1341.       g->piece = no_piece;
  1342.       g->color = side;
  1343.       (void) castle (side, f, t, 1);
  1344.       Game50 = GameCnt;
  1345.     }
  1346.   else
  1347.     {
  1348.       if (!(node->flags & capture) && (board[f] != pawn))
  1349.     {
  1350.       rpthash[side][hashkey & 0xFF]++;
  1351.       ISZERO++;
  1352.     }
  1353.       else
  1354.     Game50 = GameCnt;
  1355.       *tempsf = svalue[f];
  1356.       *tempst = svalue[t];
  1357.       g->piece = *tempb = board[t];
  1358.       g->color = *tempc = color[t];
  1359.       if (*tempc != neutral)
  1360.     {
  1361.       UpdatePieceList (*tempc, t, 1);
  1362.       /* if capture decrement pawn count */
  1363.       if (*tempb == pawn)
  1364.         {
  1365.           --PawnCnt[*tempc][column (t)];
  1366.         }
  1367.       if (board[f] == pawn)
  1368.         {
  1369.           cf = column (f);
  1370.           ct = column (t);
  1371.           /* move count from from to to */
  1372.           --PawnCnt[side][cf];
  1373.           ++PawnCnt[side][ct];
  1374.  
  1375.           /*
  1376.            * calculate increment for pawn structure
  1377.            * changes
  1378.            */
  1379.           /* doubled or more - */
  1380.           if (PawnCnt[side][ct] > (1 + PawnCnt[side][cf]))
  1381.         *INCscore -= 15;
  1382.           /* went to empty column + */
  1383.           else if (PawnCnt[side][ct] < 1 + PawnCnt[side][cf])
  1384.         *INCscore += 15;
  1385.  
  1386.           /*
  1387.            * went to outside col or empty col on one
  1388.            * side ????????
  1389.            */
  1390.           else if (ct == 0 || ct == 7 || PawnCnt[side][ct + ct - cf] == 0)
  1391.         *INCscore -= 15;
  1392.         }
  1393.       mtl[xside] -= value[*tempb];
  1394.       if (*tempb == pawn)
  1395.         pmtl[xside] -= valueP;
  1396.       UpdateHashbd (xside, *tempb, -1, t);
  1397.       *INCscore += *tempst;
  1398.       Mvboard[t]++;
  1399.     }
  1400.       color[t] = color[f];
  1401.       board[t] = board[f];
  1402.       svalue[t] = svalue[f];
  1403.       Pindex[t] = Pindex[f];
  1404.       PieceList[side][Pindex[t]] = t;
  1405.       color[f] = neutral;
  1406.       board[f] = no_piece;
  1407.       if (board[t] == pawn)
  1408.     if (t - f == 16)
  1409.       epsquare = f + 8;
  1410.     else if (f - t == 16)
  1411.       epsquare = f - 8;
  1412.       if (node->flags & promote)
  1413.     {
  1414.       board[t] = node->flags & pmask;
  1415.       if (board[t] == queen)
  1416.         HasQueen[side]++;
  1417.       else if (board[t] == rook)
  1418.         HasRook[side]++;
  1419.       else if (board[t] == bishop)
  1420.         HasBishop[side]++;
  1421.       else if (board[t] == knight)
  1422.         HasKnight[side]++;
  1423.       --PawnCnt[side][column (t)];
  1424.       mtl[side] += value[board[t]] - valueP;
  1425.       pmtl[side] -= valueP;
  1426.       UpdateHashbd (side, pawn, f, -1);
  1427.       UpdateHashbd (side, board[t], f, -1);
  1428.       *INCscore -= *tempsf;
  1429.     }
  1430.       if (node->flags & epmask)
  1431.     EnPassant (xside, f, t, 1);
  1432.       else
  1433.     UpdateHashbd (side, board[t], f, t);
  1434.       Mvboard[f]++;
  1435.     }
  1436. }
  1437.  
  1438. void
  1439. UnmakeMove (short int side,
  1440.         struct leaf *node,
  1441.         short int *tempb,
  1442.         short int *tempc,
  1443.         short int *tempsf,
  1444.         short int *tempst)
  1445.  
  1446. /*
  1447.  * Take back a move.
  1448.  */
  1449.  
  1450. {
  1451.   register short f, t, xside;
  1452.  
  1453.   xside = side ^ 1;
  1454.   f = node->f;
  1455.   t = node->t;
  1456.   Game50 = GameList[GameCnt].Game50;
  1457.   if (node->flags & cstlmask)
  1458.     (void) castle (side, f, t, 2);
  1459.   else
  1460.     {
  1461.       color[f] = color[t];
  1462.       board[f] = board[t];
  1463.       svalue[f] = *tempsf;
  1464.       Pindex[f] = Pindex[t];
  1465.       PieceList[side][Pindex[f]] = f;
  1466.       color[t] = *tempc;
  1467.       board[t] = *tempb;
  1468.       svalue[t] = *tempst;
  1469.       if (node->flags & promote)
  1470.     {
  1471.       board[f] = pawn;
  1472.       ++PawnCnt[side][column (t)];
  1473.       mtl[side] += valueP - value[node->flags & pmask];
  1474.       pmtl[side] += valueP;
  1475.       UpdateHashbd (side, (short) node->flags & pmask, -1, t);
  1476.       UpdateHashbd (side, pawn, -1, t);
  1477.     }
  1478.       if (*tempc != neutral)
  1479.     {
  1480.       UpdatePieceList (*tempc, t, 2);
  1481.       if (*tempb == pawn)
  1482.         {
  1483.           ++PawnCnt[*tempc][column (t)];
  1484.         }
  1485.       if (board[f] == pawn)
  1486.         {
  1487.           --PawnCnt[side][column (t)];
  1488.           ++PawnCnt[side][column (f)];
  1489.         }
  1490.       mtl[xside] += value[*tempb];
  1491.       if (*tempb == pawn)
  1492.         pmtl[xside] += valueP;
  1493.       UpdateHashbd (xside, *tempb, -1, t);
  1494.       Mvboard[t]--;
  1495.     }
  1496.       if (node->flags & epmask)
  1497.     {
  1498.       EnPassant (xside, f, t, 2);
  1499.     }
  1500.       else
  1501.     UpdateHashbd (side, board[f], f, t);
  1502.       Mvboard[f]--;
  1503.       if (!(node->flags & capture) && (board[f] != pawn))
  1504.     {
  1505.       rpthash[side][hashkey & 0xFF]--;
  1506.       ISZERO--;
  1507.     }
  1508.     }
  1509.   epsquare = GameList[GameCnt--].epssq;
  1510. }
  1511.  
  1512.  
  1513. void
  1514. InitializeStats (void)
  1515.  
  1516. /*
  1517.  * Scan thru the board seeing what's on each square. If a piece is found,
  1518.  * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
  1519.  * determine the material for each side and set the hashkey and hashbd
  1520.  * variables to represent the current board position. Array
  1521.  * PieceList[side][indx] contains the location of all the pieces of either
  1522.  * side. Array Pindex[sq] contains the indx into PieceList for a given
  1523.  * square.
  1524.  */
  1525.  
  1526. {
  1527.   register short i, sq;
  1528.  
  1529.   epsquare = -1;
  1530.   for (i = 0; i < 8; i++)
  1531.     {
  1532.       PawnCnt[white][i] = PawnCnt[black][i] = 0;
  1533.     }
  1534.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
  1535.   PieceCnt[white] = PieceCnt[black] = 0;
  1536.   hashbd = hashkey = 0;
  1537.   for (sq = 0; sq < 64; sq++)
  1538.     if (color[sq] != neutral)
  1539.       {
  1540.     mtl[color[sq]] += value[board[sq]];
  1541.     if (board[sq] == pawn)
  1542.       {
  1543.         pmtl[color[sq]] += valueP;
  1544.         ++PawnCnt[color[sq]][column (sq)];
  1545.       }
  1546.     Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
  1547.  
  1548.     PieceList[color[sq]][Pindex[sq]] = sq;
  1549.     hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
  1550.     hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
  1551.       }
  1552. }
  1553.